use salvo::prelude::*;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{error, info};
use chrono;
use utils::{
    response::*,
    rpc::RpcClientManager,
    transaction::{TransactionManager, TransactionStep},
    transaction_step,
};

use crate::rpc::client::SystemRpcClient;

/// 跨服务事务示例请求
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CrossServiceTransactionReq {
    /// 用户ID
    pub user_id: i64,
    /// 字典类型
    pub dict_type: String,
    /// 操作类型
    pub operation: String,
}

/// 跨服务事务示例响应
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CrossServiceTransactionRes {
    /// 事务ID
    pub transaction_id: String,
    /// 执行结果
    pub result: String,
    /// 详细信息
    pub details: Vec<String>,
}

/// 事务执行状态
#[derive(Debug, Clone)]
struct TransactionState {
    pub details: Vec<String>,
    pub dict_data_retrieved: bool,
    pub user_updated: bool,
    pub operation_logged: bool,
}

impl TransactionState {
    fn new() -> Self {
        Self {
            details: Vec::new(),
            dict_data_retrieved: false,
            user_updated: false,
            operation_logged: false,
        }
    }

    fn add_detail(&mut self, detail: String) {
        self.details.push(detail);
    }
}

/// 跨服务事务调用示例
///
/// 演示场景：
/// 1. 调用 infra 字典服务获取字典数据（成功）
/// 2. 调用 system 用户服务更新用户信息（可配置成功/失败）
/// 3. 记录操作日志
/// 4. 如果任何步骤失败，执行回滚
#[endpoint(
    operation_id = "system_transaction_crossService",
    tags("系统/事务管理"),
    request_body = CrossServiceTransactionReq,
    responses(
        (status_code = 200, description = "事务执行成功"),
        (status_code = 400, description = "请求参数错误"),
        (status_code = 500, description = "事务执行失败")
    )
)]
pub async fn cross_service_transaction(
    req: &mut Request,
) -> SalvoResult<CrossServiceTransactionRes> {
    info!("API: 跨服务事务调用示例");

    // 解析请求体
    let body = req
        .parse_json::<CrossServiceTransactionReq>()
        .await
        .map_err(|e| {
            error!("API: 解析请求体失败: {:?}", e);
            StatusError::bad_request().brief("请求体格式错误")
        })?;

    info!(
        "API: 开始跨服务事务 - user_id: {}, dict_type: {}",
        body.user_id, body.dict_type
    );

    // 获取RPC客户端管理器
    let rpc_manager = req
        .extensions()
        .get::<Arc<RpcClientManager>>()
        .ok_or_else(|| StatusError::internal_server_error().brief("RPC客户端管理器未初始化"))?;

    // 获取System RPC客户端
    let system_rpc_client = req
        .extensions()
        .get::<Arc<SystemRpcClient>>()
        .ok_or_else(|| StatusError::internal_server_error().brief("System RPC客户端未初始化"))?;

    // 创建事务管理器
    let tx_manager = TransactionManager::new();
    let transaction_id = format!("tx_{}", chrono::Utc::now().timestamp_millis());

    // 使用Arc<Mutex<TransactionState>>来安全地共享状态
    let transaction_state = Arc::new(Mutex::new(TransactionState::new()));

    // 准备事务步骤
    let steps = prepare_transaction_steps(
        rpc_manager.clone(),
        system_rpc_client.clone(),
        body,
        transaction_state.clone(),
    );

    // 执行事务
    match tx_manager.execute_transaction(steps).await {
        Ok(()) => {
            info!("跨服务事务执行成功: {}", transaction_id);
            let mut state = transaction_state.lock().await;
            state.add_detail("事务执行成功".to_string());

            let details = state.details.clone();

            salvo_success_with_message(
                CrossServiceTransactionRes {
                    transaction_id,
                    result: "success".to_string(),
                    details,
                },
                "跨服务事务执行成功",
            )
        }
        Err(e) => {
            error!("跨服务事务执行失败: {}", e);
            let mut state = transaction_state.lock().await;
            state.add_detail(format!("事务执行失败: {}", e));

            let details = state.details.clone();

            // 返回业务错误而不是StatusError，保持RESTful
            salvo_success_with_message(
                CrossServiceTransactionRes {
                    transaction_id,
                    result: "failed".to_string(),
                    details,
                },
                "跨服务事务执行失败，已执行回滚",
            )
        }
    }
}

/// 准备事务步骤
fn prepare_transaction_steps(
    rpc_manager: Arc<RpcClientManager>,
    system_rpc_client: Arc<SystemRpcClient>,
    req_body: CrossServiceTransactionReq,
    transaction_state: Arc<Mutex<TransactionState>>,
) -> Vec<TransactionStep> {
    let user_id = req_body.user_id;
    let dict_type = req_body.dict_type;
    let operation = req_body.operation;

    vec![
        // 步骤1: 调用 infra 字典服务
        transaction_step!(
            "获取字典数据",
            {
                let rpc_manager = rpc_manager.clone();
                let dict_type = dict_type.clone();
                let state = transaction_state.clone();

                async move {
                    info!("执行步骤1: 获取字典数据 - {}", dict_type);

                    // 获取字典服务连接
                    let _channel = rpc_manager
                        .get_connection("dict")
                        .await
                        .map_err(|e| AppError::rpc(&format!("连接字典服务失败: {}", e)))?;

                    // 实际调用字典服务（这里先简化实现，后续可以添加实际的gRPC调用）
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

                    info!("成功获取字典数据: {}", dict_type);

                    // 更新事务状态
                    let mut state_guard = state.lock().await;
                    state_guard.dict_data_retrieved = true;
                    state_guard.add_detail(format!("步骤1完成: 获取字典数据 - {}", dict_type));

                    Ok(())
                }
            },
            {
                let dict_type = dict_type.clone();
                let state = transaction_state.clone();

                async move {
                    info!("回滚步骤1: 清理字典数据缓存 - {}", dict_type);

                    // 清理缓存操作
                    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;

                    // 更新状态
                    let mut state_guard = state.lock().await;
                    state_guard.dict_data_retrieved = false;
                    state_guard.add_detail(format!("步骤1回滚: 清理字典数据缓存 - {}", dict_type));

                    Ok(())
                }
            }
        ),
        // 步骤2: 调用 system 用户服务
        transaction_step!(
            "更新用户信息",
            {
                let _system_rpc_client = system_rpc_client.clone();
                let operation = operation.clone();
                let state = transaction_state.clone();

                async move {
                    info!(
                        "执行步骤2: 更新用户信息 - user_id: {}, operation: {}",
                        user_id, operation
                    );

                    // 根据操作类型决定是否模拟失败
                    if operation == "fail" {
                        error!("用户服务调用失败");
                        return Err(AppError::external_service(
                            "用户服务调用失败：操作被配置为失败",
                        ));
                    }

                    // 实际调用用户服务（这里先简化实现）
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

                    info!("成功更新用户信息: user_id = {}", user_id);

                    // 更新事务状态
                    let mut state_guard = state.lock().await;
                    state_guard.user_updated = true;
                    state_guard
                        .add_detail(format!("步骤2完成: 更新用户信息 - user_id: {}", user_id));

                    Ok(())
                }
            },
            {
                let state = transaction_state.clone();

                async move {
                    info!("回滚步骤2: 恢复用户信息 - user_id: {}", user_id);

                    // 恢复用户信息操作
                    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;

                    // 更新状态
                    let mut state_guard = state.lock().await;
                    state_guard.user_updated = false;
                    state_guard
                        .add_detail(format!("步骤2回滚: 恢复用户信息 - user_id: {}", user_id));

                    Ok(())
                }
            }
        ),
        // 步骤3: 记录操作日志
        transaction_step!(
            "记录操作日志",
            {
                let _operation = operation.clone();
                let state = transaction_state.clone();

                async move {
                    info!("执行步骤3: 记录操作日志");

                    // 记录日志到数据库或日志系统
                    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;

                    info!("成功记录操作日志");

                    // 更新事务状态
                    let mut state_guard = state.lock().await;
                    state_guard.operation_logged = true;
                    state_guard.add_detail("步骤3完成: 记录操作日志".to_string());

                    Ok(())
                }
            },
            {
                let state = transaction_state.clone();

                async move {
                    info!("回滚步骤3: 删除操作日志");

                    // 删除日志记录
                    tokio::time::sleep(tokio::time::Duration::from_millis(30)).await;

                    // 更新状态
                    let mut state_guard = state.lock().await;
                    state_guard.operation_logged = false;
                    state_guard.add_detail("步骤3回滚: 删除操作日志".to_string());

                    Ok(())
                }
            }
        ),
    ]
}

/// 测试事务成功的示例
#[endpoint(
    operation_id = "system_transaction_testSuccess",
    tags("系统/事务管理"),
    responses(
        (status_code = 200, description = "测试成功"),
    )
)]
pub async fn test_transaction_success() -> SalvoResult<CrossServiceTransactionRes> {
    info!("API: 测试事务成功示例");

    let tx_manager = TransactionManager::new();
    let transaction_id = format!("test_success_{}", chrono::Utc::now().timestamp_millis());

    let steps = vec![
        transaction_step!("测试步骤1", async {
            tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
            info!("测试步骤1执行成功");
            Ok(())
        }),
        transaction_step!("测试步骤2", async {
            tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
            info!("测试步骤2执行成功");
            Ok(())
        }),
    ];

    match tx_manager.execute_transaction(steps).await {
        Ok(()) => salvo_success_with_message(
            CrossServiceTransactionRes {
                transaction_id,
                result: "success".to_string(),
                details: vec![
                    "测试步骤1完成".to_string(),
                    "测试步骤2完成".to_string(),
                    "事务执行成功".to_string(),
                ],
            },
            "测试事务执行成功",
        ),
        Err(e) => {
            error!("测试事务失败: {}", e);
            Err(StatusError::internal_server_error().brief(&e.to_string()))
        }
    }
}
